package com.tedu.aopdemo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Locale;

@Component
@Aspect//使用该注解让Spring容器知道它是一个切面类
public class SysoutAspect {

//
//    * @Before是切面类中的一个切入点注解，用于表达该方法逻辑
//    * 是在执行实际方法之前切入并运行方法中需要切入点的描述信
//    * 息（实际切入方法的签名）
//    *
//    @Before("execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))")
//    public void before(JoinPoint joinPoint){
//        //切入点方法所属的对象
//        //System.out.println("target"+joinPoint.getTarget());
//        //获取切入方法信息，（Signature,这里表示方法签名,通过Signature
//        //                获取该方法名字（.getName））
//        //System.out.println(joinPoint.getSignature().getName());
//        //获取切入方法的参数（实参）
//        //System.out.println("参数:"+ Arrays.toString(joinPoint.getArgs()));
//        //获取切入点的方法名
//        String methodName = joinPoint.getSignature().getName();
//        //获取切入点该方法所属的类
//        String className = joinPoint.getTarget().getClass().getSimpleName();
//        //获取切入点调用方法实际传入的参数
//        String args = Arrays.toString(joinPoint.getArgs());
//        System.out.println("开始调用"+className+"."+methodName+"(),实参为:"+args);
//    }
//
//    * @AfterReturning表四切入点为实际方法调用完毕并返回结果后调用
//    * 该切入点方法除了可以获取切入点信息（joinPoint），还可以获取实际方法
//    * 调用后返回的结果（returnVal）
//    *
//    @AfterReturning(
//            value = "execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))",
//            returning = "returnValue"//说明将实际方法返回值传递给下面方法的哪个参数
//    )
//    public void afterReturning(JoinPoint joinPoint,Object returnValue){
//        String methodName = joinPoint.getSignature().getName();
//        String className = joinPoint.getTarget().getClass().getSimpleName();
//        System.out.println(className+"."+methodName+"()执行完毕，返回值为:"+returnValue);
//    }
//
//    * @After切入点是在一个方法执行完毕后。无论该方法是否抛出异常，最后都会走该切面
//    * 注意该切面不能获取方法返回值
//    *
//    @After("execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))")
//    public void after(JoinPoint joinPoint){
//        String methodName = joinPoint.getSignature().getName();
//        String className = joinPoint.getTarget().getClass().getSimpleName();
//        System.out.println(className+"."+methodName+"()完毕");
//    }
//
//    * @AfterThrowing切入点是在实际方法抛出异常后进行
//    *
//    @AfterThrowing(
//            value = "execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))",
//            throwing = "e"//指定将实际方法抛出的异常传递给下面方法的哪个参数
//    )
//    public void AfterThrowing(JoinPoint joinPoint,Exception e){
//        String methodName = joinPoint.getSignature().getName();
//        String className = joinPoint.getTarget().getClass().getSimpleName();
//        System.out.println(className+"."+methodName+"()抛出异常了:"+e.getMessage());
//    }
    /*
    * @Around切入点结合了上述几个
    * */
    /*@Around("execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))")
    public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        //@Before里切入的逻辑写在这里
        System.out.println(className+"."+methodName+"()开始执行，参数为:"+args);
        try {
            //实际方法执行，并接收该方法的返回值
            //@AfterReturning
            Object returnValue = joinPoint.proceed();//CalculatorImpl.add执行
            System.out.println(className+"."+methodName+"()执行完毕");
            return returnValue;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            //@After
            System.out.println(className+"."+methodName+"()最终执行完毕");
        }
    }*/
    @Around("execution(public int com.tedu.aopdemo.aop.CalculatorImpl.*(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println(className+"."+methodName+"():开始执行,参数为"+args);
        try {
            Object returnValue = joinPoint.proceed();
            System.out.println(className+"."+methodName+"()执行完毕");
            return returnValue;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println(className+"."+methodName+"()最终执行完毕");
        }
    }
}













